﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using EntityMap.Meta;
using System.Reflection;
using System.Collections.ObjectModel;

namespace EntityMap
{
    public partial class EntityManager
    {
        /// <summary>
        /// This method execute sql statement defined in xml and return a typed collection.
        /// </summary>
        /// <typeparam name="T">entity</typeparam>
        /// <param name="statementId">id of statement defined in xml</param>
        /// <param name="parameters">parameter</param>
        /// <returns>A typed collection of entity</returns>
        public IList<T> QueryForList<T>( string statementId )
        {
            return QueryForList<T>( statementId, null );
        }

        public IList<T> QueryForList<T>( string statementId, object objParameter )
        {
            IList<T> entities = new Collection<T>();

            Type entityType = typeof( T );

            using( SqlConnection conn = new SqlConnection( _connectionString ) )
            {
                EntityInfo einfo = this.GetEntityInfo( entityType );

                // get statement information
                SelectStatement sqlStatement = einfo.GetStatement( statementId ) as SelectStatement;

                // get map information of statement
                ResultMap rMap = einfo.GetResultMap( sqlStatement.ResultMap );

                SqlParameter[] parameters = null;

                if( objParameter != null )
                {
                    ParameterMap pMap = einfo.GetParameterMap( sqlStatement.ParameterMap );

                    parameters = pMap.GetSqlParameters( objParameter );
                }

                using( SqlCommand cmd = sqlStatement.GetSqlCommand( conn, parameters ) )
                {
                    conn.Open();

                    SqlDataReader reader = cmd.ExecuteReader();

                    // create and fill new object
                    while( reader.Read() )
                    {
                        T obj = Activator.CreateInstance<T>();

                        foreach( Field fi in rMap.Fields )
                        {
                            PropertyInfo pinfo = entityType.GetProperty( fi.Property );

                            pinfo.SetValue( obj, reader[fi.Column], null );
                        }

                        entities.Add( obj );
                    }
                }
            }
            return entities;
        }

        public T QueryForSingle<T>( string statementId, object objParameter )
        {
            T obj = Activator.CreateInstance<T>();

            Type entityType = typeof( T );

            using( SqlConnection conn = new SqlConnection( _connectionString ) )
            {
                EntityInfo einfo = this.GetEntityInfo( entityType );

                // get statement information
                SelectStatement sqlStatement = einfo.GetStatement( statementId ) as SelectStatement;

                // get map information of statement
                ResultMap map = einfo.GetResultMap( sqlStatement.ResultMap );

                SqlParameter[] parameters = null;

                if( objParameter != null )
                {
                    ParameterMap pMap = einfo.GetParameterMap( sqlStatement.ParameterMap );

                    parameters = pMap.GetSqlParameters( objParameter );
                }

                using( SqlCommand cmd = sqlStatement.GetSqlCommand( conn, parameters ) )
                {
                    conn.Open();

                    SqlDataReader reader = cmd.ExecuteReader();

                    // create and fill new object
                    if( reader.Read() )
                    {
                        foreach( Field fi in map.Fields )
                        {
                            PropertyInfo pinfo = entityType.GetProperty( fi.Property );

                            pinfo.SetValue( obj, reader[fi.Column], null );
                        }
                    }
                }
            }

            return obj;
        }

        //public DataTable QueryForTable<T>( string statementId, params DataParameter[] parameters )
        //{
        //    DataTable result = new DataTable();

        //    Type entityType = typeof( T );

        //    using( SqlConnection conn = new SqlConnection( _connectionString ) )
        //    {
        //        EntityInfo einfo = this.GetEntityInfo( entityType );

        //        // get statement information
        //        SelectStatement sqlStatement = einfo.GetStatement( statementId ) as SelectStatement;

        //        using( SqlCommand cmd = sqlStatement.GetSqlCommand( conn ) )
        //        {
        //            // set parameters
        //            if( parameters != null )
        //            {
        //                foreach( DataParameter dp in parameters )
        //                {
        //                    cmd.Parameters[dp.Name].Value = dp.Value;
        //                }
        //            }

        //            conn.Open();

        //            SqlDataReader reader = cmd.ExecuteReader();

        //            if( reader.Read() )
        //            {
        //                result.Load( reader );
        //            }
        //        }
        //    }
        //    return result;
        //}
    }
}
